package com.gsi.webstore.platform.storefront.pipelet;

import java.util.Iterator;
import java.util.Map;

import com.gsi.webstore.platform.adapter.storelocator.capi.StoreLocatorManager;
import com.gsi.webstore.platform.adapter.storelocator.internal.client.data.Storefront;
import com.gsi.webstore.platform.adapter.storelocator.internal.client.data.StorefrontTimingsDetails;
import com.intershop.beehive.bts.capi.orderprocess.LineItem;
import com.intershop.beehive.bts.capi.orderprocess.basket.Basket;
import com.intershop.beehive.core.capi.domain.Domain;
import com.intershop.beehive.core.capi.localization.LocaleInformation;
import com.intershop.beehive.core.capi.localization.LocalizationProvider;
import com.intershop.beehive.core.capi.log.Logger;
import com.intershop.beehive.core.capi.naming.NamingMgr;
import com.intershop.beehive.core.capi.pipeline.Pipelet;
import com.intershop.beehive.core.capi.pipeline.PipeletExecutionException;
import com.intershop.beehive.core.capi.pipeline.PipelineDictionary;
import com.intershop.beehive.core.capi.request.Request;
import com.intershop.beehive.pipeline.capi.PipelineException;

/**
 * 
 */
public class CreateMultichannelCartLineItemAttributes extends Pipelet
{
    private static final String RANGE_KEY = "multichannel.ispu.storefront.timings.range";
    private static final String CLOSED_KEY = "multichannel.ispu.storefront.timings.closed";
    private static final String OPEN_24HR_KEY = "multichannel.ispu.storefront.timings.24hrs";
    
    private static final String MC_FULFILLMENT_CHANNEL_TYPE = "MC_FulfillmentChannelType";
    private static final String MC_STORE_FRONT_CODE = "MC_StoreFrontCode";
    private static final String MC_STORE_FRONT_NAME = "MC_StoreFrontName";
    private static final String MC_STORE_FRONT_DIRECTIONS = "MC_StoreFrontDirections";
    private static final String MC_STORE_FRONT_HOURS = "MC_StoreFrontHours";
    private static final String MC_STORE_FRONT_EMAIL = "MC_StoreFrontEmail";
    private static final String MC_ADDRESS1 = "MC_DisplayAddress1";
    private static final String MC_ADDRESS2 = "MC_DisplayAddress2";
    private static final String MC_ADDRESS3 = "MC_DisplayAddress3";
    private static final String MC_CITY = "MC_DisplayCity";
    private static final String MC_STATE = "MC_DisplayState";
    private static final String MC_ZIP = "MC_DisplayZip";
    private static final String MC_COUNTRY = "MC_DisplayCountry";
    private static final String MC_PHONE = "MC_DisplayPhone";
    
    private static final String FULFILLMENT_METHOD_ATTRIBUTE = "MC_FULFILLMENT_METHOD";
    private static final String FULFILLMENT_METHOD_STS = "STS";
    private static final String FULFILLMENT_METHOD_ISPU = "ISPU";
    private static final String STORE_ID_ATTRIBUTE = "STORE_ID";
    
    private static final String OMS_SHIP_TO_STORE = "SHIP_TO_STORE";
    private static final String OMS_STORE_PICK_UP = "STORE_PICK_UP";
    private static final String OMS_SHIP_TO_HOME = "SHIP_TO_HOME";
    
    LocalizationProvider localizationProvider;
    StoreLocatorManager storeLocatorMgr;
    
    /**
     * Constant used to access the pipeline dictionary with key 'Cart'
     */
    public static final String DN_CART = "Cart";
    /**
     * Constant used to access the pipeline dictionary with key 'StorefrontLineItemMap'
     */
    public static final String DN_STOREFRONT_LINE_ITEM_MAP = "StorefrontLineItemMap";
    /**
     * Constant used to access the pipeline dictionary with key 'CurrentRequest'
     */
    public static final String DN_CURRENT_REQUEST = "CurrentRequest";

    /**
     * The pipelet's execute method is called whenever the pipelets gets
     * executed in the context of a pipeline and a request. The pipeline
     * dictionary valid for the currently executing thread is provided as a
     * parameter.
     * 
     * @param dict
     *            The pipeline dictionary to be used.
     * @throws PipeletExecutionException
     *             Thrown in case of severe errors that make the pipelet execute
     *             impossible (e.g. missing required input data).
     */
    public int execute(PipelineDictionary dict)
    throws PipeletExecutionException {        
        // lookup 'CurrentRequest' in pipeline dictionary
        Request currentRequest = (Request)dict.get(DN_CURRENT_REQUEST);
        if (null == currentRequest)
        {
            throw new PipeletExecutionException(
                            "Mandatory input parameter 'CurrentRequest' not available in pipeline dictionary.");
        }
        
        // lookup 'StorefrontLineItemMap' in pipeline dictionary
        @SuppressWarnings("unchecked")
        Map<String, Storefront> storefrontLineItemMap = (Map<String, Storefront>)dict.get(DN_STOREFRONT_LINE_ITEM_MAP);
        if (null == storefrontLineItemMap)
        {
            throw new PipeletExecutionException(
                            "Mandatory input parameter 'StorefrontLineItemMap' not available in pipeline dictionary.");
        }
        
        // lookup 'Cart' in pipeline dictionary
        Basket cart = (Basket)dict.get(DN_CART);
        if (null == cart)
        {
            throw new PipeletExecutionException("Mandatory input parameter 'Cart' not available in pipeline dictionary.");
        }
        
        Domain domain = currentRequest.getChannelSite();
        LocaleInformation localeInfo = currentRequest.getLocale();
        Iterator<LineItem> lineItemsIterator = cart.createLineItemsIterator();
        
        while (lineItemsIterator.hasNext()) {
            LineItem lineItem = lineItemsIterator.next();
            String lineItemFulfillmentMethod = lineItem.getString(FULFILLMENT_METHOD_ATTRIBUTE);
            if (FULFILLMENT_METHOD_STS.equals(lineItemFulfillmentMethod) || 
                FULFILLMENT_METHOD_ISPU.equals(lineItemFulfillmentMethod)) {
                
                //Map webstore fulfillment method to OMS fulfillment method
                if (FULFILLMENT_METHOD_STS.equals(lineItemFulfillmentMethod)) {
                    lineItem.putString(MC_FULFILLMENT_CHANNEL_TYPE, OMS_SHIP_TO_STORE);
                } else if (FULFILLMENT_METHOD_ISPU.equals(lineItemFulfillmentMethod)) {
                    lineItem.putString(MC_FULFILLMENT_CHANNEL_TYPE, OMS_STORE_PICK_UP);
                }
                
                Storefront storefront = storefrontLineItemMap.get(lineItem.getUUID());
                if (storefront == null) {
                    Long storeFrontId = (Long)lineItem.getLong(STORE_ID_ATTRIBUTE);
                    if (storeFrontId == null) {
                        Logger.warn(this, "Store front ID could not be found for cart line item " + lineItem.getUUID() + ".");
                        continue;
                    }
                    storefront = storeLocatorMgr.getStorefront(storeFrontId, localeInfo.getLocaleID());
                    if (storefront == null) {
                        Logger.warn(this, "Store front ID = {0} could not be found.", storeFrontId);
                        continue;
                    }
                }
                
//                lineItem.putString(MC_FULFILLMENT_CHANNEL_TYPE, lineItemFulfillmentMethod);
                lineItem.putString(MC_STORE_FRONT_CODE, storefront.getStoreCode());
                lineItem.putString(MC_STORE_FRONT_NAME, storefront.getStoreName());
                lineItem.putString(MC_STORE_FRONT_DIRECTIONS, getStorefrontDirectionsLink(storefront));
                lineItem.putString(MC_STORE_FRONT_HOURS, getStorefrontHours(storefront, domain, localeInfo));
                lineItem.putString(MC_STORE_FRONT_EMAIL, storefront.getEmail());
                if (storefront.getAddress1() != null) {
                    lineItem.putString(MC_ADDRESS1, storefront.getAddress1());
                }
                if (storefront.getAddress2() != null) {
                    lineItem.putString(MC_ADDRESS2, storefront.getAddress2());
                }
                if (storefront.getAddress3() != null) {
                    lineItem.putString(MC_ADDRESS3, storefront.getAddress3());
                }
                
                lineItem.putString(MC_CITY, storefront.getCity());
                lineItem.putString(MC_STATE, storefront.getStateCode());
                lineItem.putString(MC_ZIP, storefront.getZipcode());
                lineItem.putString(MC_COUNTRY, storefront.getCountryCode());
                lineItem.putString(MC_PHONE, storefront.getPhoneNumber());
            } else {
                lineItem.putString(MC_FULFILLMENT_CHANNEL_TYPE, OMS_SHIP_TO_HOME);
            }
        }
        
        return PIPELET_NEXT;
    }
    
    private String getStorefrontDirectionsLink(Storefront storefront) {
        String url = "http://maps.google.com/maps?f=q&source=s_q&hl=en&q=";
        String storefrontAddress = "";
            
        if (storefront.getAddress1() != null) {
            storefrontAddress += storefront.getAddress1() + " ";
        }
        if (storefront.getAddress2() != null) {
            storefrontAddress += storefront.getAddress2() + " ";
        }
        if (storefront.getAddress3() != null) {
            storefrontAddress += storefront.getAddress3() + " ";
        }
        
        storefrontAddress +=   storefront.getCity() + ", " +
                               storefront.getStateCode() + " " +
                               storefront.getZipcode() + ", " +
                               storefront.getCountryCode();
        
        return url + storefrontAddress;
    }
    
    private String getStorefrontHours(Storefront storefront, Domain domain, LocaleInformation localeInfo) {
        String hours = "";
        StorefrontTimingsDetails timings = storefront.getStorefrontTimingsDetails();
        
        //Monday
        if (timings.isClosedMon()) {
            hours += localizationProvider.getText(CLOSED_KEY, domain, localeInfo) + "|";
        } else if (timings.isOpen24HrMon()) {
            hours += localizationProvider.getText(OPEN_24HR_KEY, domain, localeInfo) + "|";
        } else {
            hours += localizationProvider.getText(RANGE_KEY, domain, localeInfo, timings.getOpeningTimeMon(), timings.getClosingTimeMon()) + "|";
        }
        
        //Tuesday
        if (timings.isClosedTue()) {
            hours += localizationProvider.getText(CLOSED_KEY, domain, localeInfo) + "|";
        } else if (timings.isOpen24HrTue()) {
            hours += localizationProvider.getText(OPEN_24HR_KEY, domain, localeInfo) + "|";
        } else {
            hours += localizationProvider.getText(RANGE_KEY, domain, localeInfo, timings.getOpeningTimeTue(), timings.getClosingTimeTue()) + "|";
        }
        
        //Wednesday
        if (timings.isClosedWed()) {
            hours += localizationProvider.getText(CLOSED_KEY, domain, localeInfo) + "|";
        } else if (timings.isOpen24HrWed()) {
            hours += localizationProvider.getText(OPEN_24HR_KEY, domain, localeInfo) + "|";
        } else {
            hours += localizationProvider.getText(RANGE_KEY, domain, localeInfo, timings.getOpeningTimeWed(), timings.getClosingTimeWed()) + "|";
        }
        
        //Thursday
        if (timings.isClosedThu()) {
            hours += localizationProvider.getText(CLOSED_KEY, domain, localeInfo) + "|";
        } else if (timings.isOpen24HrThu()) {
            hours += localizationProvider.getText(OPEN_24HR_KEY, domain, localeInfo) + "|";
        } else {
            hours += localizationProvider.getText(RANGE_KEY, domain, localeInfo, timings.getOpeningTimeThu(), timings.getClosingTimeThu()) + "|";
        }
        
        //Friday
        if (timings.isClosedFri()) {
            hours += localizationProvider.getText(CLOSED_KEY, domain, localeInfo) + "|";
        } else if (timings.isOpen24HrFri()) {
            hours += localizationProvider.getText(OPEN_24HR_KEY, domain, localeInfo) + "|";
        } else {
            hours += localizationProvider.getText(RANGE_KEY, domain, localeInfo, timings.getOpeningTimeFri(), timings.getClosingTimeFri()) + "|";
        }
        
        //Saturday
        if (timings.isClosedSat()) {
            hours += localizationProvider.getText(CLOSED_KEY, domain, localeInfo) + "|";
        } else if (timings.isOpen24HrSat()) {
            hours += localizationProvider.getText(OPEN_24HR_KEY, domain, localeInfo) + "|";
        } else {
            hours += localizationProvider.getText(RANGE_KEY, domain, localeInfo, timings.getOpeningTimeSat(), timings.getClosingTimeSat()) + "|";
        }
        
        //Sunday
        if (timings.isClosedSun()) {
            hours += localizationProvider.getText(CLOSED_KEY, domain, localeInfo) + "|";
        } else if (timings.isOpen24HrSun()) {
            hours += localizationProvider.getText(OPEN_24HR_KEY, domain, localeInfo) + "|";
        } else {
            hours += localizationProvider.getText(RANGE_KEY, domain, localeInfo, timings.getOpeningTimeSun(), timings.getClosingTimeSun());
        }
        return hours;
    }
    
    public void init() throws PipelineException {
        localizationProvider = (LocalizationProvider)NamingMgr.getInstance().lookupProvider("LocalizationProvider");
        storeLocatorMgr = (StoreLocatorManager)NamingMgr.getManager(StoreLocatorManager.class);
    }
}